#include  <Uefi.h>
#include  <Library/UefiLib.h>
#include  <Library/ShellCEntryLib.h>
#include  <Library/IoLib.h>

extern  EFI_SYSTEM_TABLE    *gST;
extern  EFI_BOOT_SERVICES   *gBS;

#define TIMEOUT         0xFFFF
#define ECCOMMAND       0x66
#define ECSTATUS        0x66
#define ECDATA          0x62
#define EC_S_OBF           BIT0
#define EC_S_IBF           BIT1
#define ECREADCMD          0x80

UINT8   MemBuffer[16][16];

void   WaitIBF() {
  UINT32 Status;
  UINTN Count;

  Count = 0;
  Status = 0;

  Status = IoRead8 (ECSTATUS);
  while (((Status & EC_S_IBF) != 0)||(Count>TIMEOUT)) {
    Status = IoRead8 (ECSTATUS);
    Count++;
  }
}

void    WaitOBF() {
  UINT32 Status;
  UINTN Count;

  Count = 0;
  Status = 0;

  Status = IoRead8 (ECSTATUS);
  while (((Status & EC_S_OBF) == 0)||(Count>TIMEOUT)) {
    Status = IoRead8 (ECSTATUS);
    Count++;
  }
}

UINT8 ReadECRam(UINT8 Index) {
  WaitIBF();               //1
  IoWrite8(ECCOMMAND,0x80);//2
  WaitIBF();               //3a
  IoWrite8(ECDATA, Index); //3b
  WaitOBF();               //4a
  return IoRead8(ECDATA); //4b
}

void GetData()
{
        UINT8   i,j;
        for (i=0;i<16;i++)
          for (j=0;j<16;j++) {
             MemBuffer[i][j]=ReadECRam(i*16+j);
          }
}
void ShowData()
{
        UINT8   i,j;
        Print(L"    ");
        for (i=0;i<16;i++) Print(L"%02X ",i);
        Print(L"\n");
        for (i=0;i<16;i++) {
                Print(L"%02X: ",i);
           for (j=0;j<16;j++) {
                Print(L"%02X ",MemBuffer[i][j]);
           }
           Print(L"\n");
        }
        Print(L"\n");
}
/***
  Print a welcoming message.

  Establishes the main structure of the application.

  @retval  0         The application exited normally.
  @retval  Other     An error occurred.
***/
INTN
EFIAPI
ShellAppMain (
  IN UINTN Argc,
  IN CHAR16 **Argv
  )
{
  EFI_INPUT_KEY         Key;

  Key.ScanCode=SCAN_NULL;
  while (SCAN_UP!=Key.ScanCode)
    {
        gST->ConOut->ClearScreen(gST->ConOut);
        GetData();
        ShowData();
        gST -> ConIn -> ReadKeyStroke(gST->ConIn,&Key);   
        Print(L"Press Arrow-Up to exit\n");
        gBS->Stall(1000000UL);
    }

    return(0);
}
